package com.yanx.framework.aspect;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.yanx.common.annotation.Pagination;
import com.yanx.common.core.vo.BasePageVo;
import com.yanx.common.page.PageConstant;
import com.yanx.common.utils.String_;
import com.yanx.common.utils.ThreadLocal_;
import com.yanx.common.utils.Url_;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Aspect
@Component
public class PageAspect {
    @Autowired
    private HttpServletRequest request;

    /**
     * 定义请求日志切入点
     */
    @Pointcut(value = "@annotation(pagination)")
    public void serviceStatistics(Pagination pagination) {

    }

    /**
     * 前置通知
     *
     * @param joinPoint
     * @param pagination
     */
    @Before(value = "serviceStatistics(pagination)")
    private void doBefore(JoinPoint joinPoint, Pagination pagination) {
        Map<String, String> queryMap = new HashMap<>();

        String method = request.getMethod();
        //获取请求参数集合并进行遍历拼接
        if ("POST".equals(method)) {
            Object[] args = joinPoint.getArgs();
            if (args.length > 0) {
                Object object = args[0];
                queryMap = getKeyAndValue(object);
            }
        } else if ("GET".equals(method)) {
            queryMap = Url_.splitQuery(request.getQueryString());
        }

        //common
        ThreadLocal_.set(PageConstant.TYPE, pagination.type());
        ThreadLocal_.set(PageConstant.PARAM_ORDERBY, Convert.toStr(queryMap.get("orderby"), pagination.orderBy()));
        ThreadLocal_.set(PageConstant.PARAM_ORDERBY_FIELD, Convert.toStr(queryMap.get("orderbyfield"), "id"));
        ThreadLocal_.set(PageConstant.TOTAL_SWITCH, Convert.toBool(queryMap.get("total"), pagination.total()));

        if (String_.equals(pagination.type(), PageConstant.Type.CURSOR)) {
            //cursor
            ThreadLocal_.set(PageConstant.PARAM_CURSOR_AFTER, Convert.toLong(queryMap.get("after"), 0L));
            ThreadLocal_.set(PageConstant.PARAM_CURSOR_BEFORE, Convert.toLong(queryMap.get("before"), 0L));
            ThreadLocal_.set(PageConstant.PARAM_CURSOR_LIMIT, Convert.toInt(queryMap.get("limit"), pagination.limit()));
            queryMap.remove("nextUrl");
            ThreadLocal_.set(PageConstant.CURSOR_LINK, Url_.appendParams(request.getRequestURI(), queryMap));
        } else {
            //offset
            ThreadLocal_.set(PageConstant.PARAM_OFFSET_PAGE, Convert.toInt(queryMap.get("page"), Convert.toInt(queryMap.get("pageNo"), Convert.toInt(queryMap.get("pageNum"), 1))));
            ThreadLocal_.set(PageConstant.PARAM_OFFSET_SIZE, Convert.toInt(queryMap.get("size"), Convert.toInt(queryMap.get("pageSize"), pagination.limit())));
        }
    }

    public static Map<String, String> getKeyAndValue(Object obj) {
        Map<String, String> map = new HashMap<>();
        if (obj != null) {
            BeanUtil.beanToMap(obj).forEach((k, v) -> {
                if (v != null) {
                    map.put(k, v.toString());// 设置键值
                }
            });
        }
//
//        // 得到类对象
//        Class userCla = obj.getClass();
//        /* 得到类中的所有属性集合 */
//        Field[] fs = userCla.getDeclaredFields();
//        for (int i = 0; i < fs.length; i++) {
//            Field f = fs[i];
//            f.setAccessible(true); // 设置些属性是可以访问的
//            try {
//                Object val = f.get(obj);
//                if (val != null) {
//                    map.put(f.getName(), val.toString());// 设置键值
//                }
//            } catch (IllegalArgumentException e) {
//                e.printStackTrace();
//            } catch (IllegalAccessException e) {
//                e.printStackTrace();
//            }
//        }
        return map;
    }

    /**
     * 返回通知
     *
     * @param pagination
     * @param returnValue
     */
    @AfterReturning(value = "serviceStatistics(pagination)", returning = "returnValue")
    private void doAfterReturning(Pagination pagination, Object returnValue) {
        if (String_.equals(pagination.type(), PageConstant.Type.CURSOR)) {
            if (returnValue instanceof List) {
                List list = (List) returnValue;
                if (ObjectUtil.isNotEmpty(list)) {
                    BasePageVo first = (BasePageVo) list.get(0);
                    ThreadLocal_.set(PageConstant.CURSOR_BEFORE, first.getId() + "");
                    BasePageVo last = (BasePageVo) list.get(list.size() - 1);
                    ThreadLocal_.set(PageConstant.CURSOR_AFTER, last.getId() + "");
                }

                int limit = ThreadLocal_.get(PageConstant.PARAM_CURSOR_LIMIT);
                if (list.size() >= limit) {
                    ThreadLocal_.set(PageConstant.CURSOR_HASNEXT, true);
                }
            }
        } else {

        }
    }

}
